home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
lang
/
mc302
/
laptalk
/
laptalk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-18
|
37KB
|
1,538 lines
/*
* LAPTALK terminal program
*
* Copyright 1991-1994 Dave Dunfield
* All rights reserved.
*
* Permission granted for personal (non-commercial) use only.
*
* Compile with DDS MICRO-C compiler in 8086 TINY model.
*
* Compile command: cc laptalk -fop
*/
#include <stdio.h>
#include <window.h>
#include <comm.h>
#include <file.h>
/* General definitions */
#define FSIZE 32 /* Max. size of a file name */
#define NFILES 8 /* Number of file entries */
#define FWIDTH 65 /* Width of file entries */
/* Script processor definitions */
#define NUM_VARS 26 /* Number of variables allowed */
#define CAPTURE_SIZE 256 /* Sizeof TX capture buffer */
/*
* Configuration parameters
* These MUST all be initialized in order to have default values,
* and to insure that they are of the same storage class.
*/
char homedir[FSIZE+1] = 0; /* Default home directory */
char filename[FSIZE+1] = { "*.*" }; /* Last filename accessed */
char scriptfile[FSIZE+1]= { "*" }; /* Script file */
int com_port = 0, /* Com port (1) */
baud = 5, /* Baud rate (9600) */
parity = 4, /* Parity (None) */
dbits = 3, /* Data bits (8) */
sbits = 0, /* Stop bits (1) */
flow = 1; /* Flow control (Enabled) */
int hangup_delay = 3, /* Delay to hangup modem */
key_string_delay = 0, /* Delay between chars in TX'd strings */
upl_char_delay = 0, /* Delay between characters on upload */
upl_line_delay = 0, /* Delay between lines on upload */
upl_sync_char = 0; /* Upload synchronize character */
int tab_size = 8; /* Spacing of tab stops */
char alarm = 0, /* Sound alarm on errors */
echotty = 0, /* Echo data sent in tty */
echosnd = 0, /* Echo data sent in scripts */
sendlf = 0, /* Line-feed in ASCII upload */
sendnull = 0, /* Send space on null lines */
hangmdm = 0; /* Hangup modem on exit */
int attrs[] = { /* Window attributes */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 0: Main TTY screen */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 1: Attribute */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 2: Attribute */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 3: Attribute */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 4: Attribute */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 5: Attribute */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x07, /* 6: Attribute */
WSAVE|WCOPEN|WLF|WSCROLL|WWRAP|0x70, /* 7: Attribute */
WSAVE|WCOPEN|0x70, /* 8: Status line */
WSAVE|WCOPEN|WBOX2|0x70, /* 9: Error Messages */
WSAVE|WCOPEN|WBOX3|0x70, /* 10: String prompts */
WSAVE|WCOPEN|WBOX1|0x70, /* 11: Setup screen 1 */
WCOPEN|WBOX2|0x70 }; /* 12: Setup screen 2 */
char protocols[NFILES][FWIDTH] = { "ASCII \\F\\A" };
char scripts[NFILES][FWIDTH] = { 0 };
/* Window attribute identifiers */
#define TTY 0
#define STATUS 8
#define ERROR 9
#define STRING 10
#define SETUP1 11
#define SETUP2 12
/*
* ANSI (VT100) Function key translation table
*/
char *ansi_keys[] = {
"\x1B[A", "\x1B[B", "\x1B[D", "\x1B[C", /* Arrow keys */
"\x1BOR", "\x1BOS", "\x1BOP", "\x1BOQ", /* PgUp, Pgdn, Home, End */
"\x1BOM", "\x1BOm", "\x1BOp", /* Keypad '+','-' Insert */
"\x7F", "\x08", /* Delete & Backspace */
"\x1BOq", "\x1BOr", "\x1BOs", "\x1BOt", /* F1, F2, F3 & F4 */
"\x1BOu", "\x1BOv", "\x1BOw", "\x1BOx", /* F5, F6, F7 & F8 */
"\x1BOy", "\x1BOz", /* F9 & F10 */
"\x1BOl", "\x1BOn", 0, 0 }; /* Control: Pgup, Pgdn, Home, End */
char *main_menu[] = { /* Main function menu */
"Function menu",
"Download file",
"Upload file",
"Kill capture",
"Perform script",
"Hangup modem",
"Clear screen",
"Configuration",
"Shell to DOS",
"Exit to DOS",
0 };
char *config_menu[] = { /* System configuration menu */
"General switches",
"General parameters",
"Serial port settings",
"Transfer protocols",
"Function menu scripts",
"Video attributes",
"Load configuration",
"Save configuration",
0 }
char *switches[] = { /* General switch names */
"Sound ALARM in messages",
"Echo data sent in tty",
"Echo data sent in scripts",
"Send LF on ASCII uploads",
"Send space in NULL lines",
"Drop DTR+RTS on EXIT" };
char *serial_menu[] = { /* Serial configuration menu */
"Comm port",
"Baudrate",
"Parity",
"Data bits",
"Stop bits",
"Flow control",
0 }
char *setup_form[] = { /* To set general parameters */
52<<8|9,
"\x01\x00\x20Home directory:",
"\x01\x01\x82Tab spacing:",
"\x01\x02\x85Modem hangup delay:",
"\x01\x03\x85String TX char delay:",
"\x01\x04\x85ASCII Upload char delay:",
"\x01\x05\x85ASCII Upload line delay:",
"\x01\x06\x83ASCII Upload sync. char:",
0 };
char *string_form[] = { /* External protocols & scripts */
68<<8|10,
"\x00\x00\x401:",
"\x00\x01\x402:",
"\x00\x02\x403:",
"\x00\x03\x404:",
"\x00\x04\x405:",
"\x00\x05\x406:",
"\x00\x06\x407:",
"\x00\x07\x408:",
0 };
char *menus[] = {
"Main TTY screen",
"Video attribute 1",
"Video attribute 2",
"Video attribute 3",
"Video attribute 4",
"Video attribute 5",
"Video attribute 6",
"Video attribute 7",
"Status line",
"Error message box's",
"String input fields",
"Main menu's",
"Sub menu's" };
char *commands[] = { /* Script commands */
"print", "echo", "assign", "equate", "input", "read", "menu", "if#",
"ifeq", "ifne", "ifnot", "if", "goto", "skip", "stop", "call", "chain",
"send", "scan", "flush", "wait", "upload", "download", "close", "dos",
"visible", "invisible", "abort", "error", "message", "hangup", "terminal",
"clear", "config", "exittodos", "rem", 0 };
char *operators[] = { /* Operators in script expression parser */
"+", "-", "*", "/", "%", "&", "|", "^", "<<", ">>",
"==", "!=", ">=", "<=", ">", "<",
0 };
/* Common strings */
char uplprompt[] = { "File to UPLOAD" };
char dnlprompt[] = { "File to DOWNLOAD" };
char cnfprompt[] = { "Configuration filename" };
char cnfext[] = { ".CFG" };
/* Uart configuration static data tables */
unsigned baudvalue[] =
{ _110, _300, _1200, _2400, _4800, _9600, _19200, _38400 };
char *baudtext[] =
{ "110", "300", "1200", "2400", "4800", "9600", "19200", "38400", 0 };
char *paritytext[] = { "Odd", "Even", "Mark", "Space", "None", 0 };
char *onetwo[] = { "One", "Two", 0 };
char *onefour[] = { "One", "Two", "Three", "Four", 0 };
char *fiveight[] = { "Five", "Six", "Seven", "Eight", 0 };
char *flowtext[] = { "Disabled", "Enabled", 0 };
/* Open window pointers */
struct WINDOW *tty, *status;
/* Global window pointer (to retain postion) */
int main_p = 0, config_p = 0, serial_p = 0, proto_p = 0, script_p = 0;
/* Misc global variables */
int signals = SET_DTR|SET_RTS|OUTPUT_2;
int key_delay = 0, status_name_ptr = 0;
char *key_ptr = 0, *status_names[10], sent_cr, last_rx;
char cnffile[FSIZE+1] = { "LAPTALK" };
FILE *fp, *log_fp = 0, *upl_fp = 0; /* Upload/Download file pointers */
/* Globals used by the script interpreter */
unsigned line, cptr = 0, savenv[3];
char *optr, capture[CAPTURE_SIZE], invisible, abort_flag, interactive = -1;
char buffer[80];
extern register message_box(), write_status();
/*
* Main program
*/
main(argc, argv)
int argc;
char *argv[];
{
optr = cnffile;
for(line=1; line < argc; ++line) {
tty = argv[line];
switch((*tty++ << 8)|*tty++) {
case 'c=' : /* Specify CONFIG file */
case 'C=' :
optr = tty;
break;
case '-i' : /* Disable interactive session */
case '-I' :
interactive = 0;
break;
case '-?' :
case '?' << 8:
abort("\nUse: LAPTALK [-i c=file] [script command]\n\nCopyright 1991-1994 Dave Dunfield\nAll rights reserved.\n");
default:
while(argc < 20)
argv[argc++] = 0;
argc = 0; } }
parse_filename(buffer, cnfext);
if(fp = fopen(buffer, "rb")) {
fread(homedir, ansi_keys-homedir, fp);
fclose(fp); }
status = wopen(0, 24, 80, 1, attrs[STATUS]);
tty = wopen(0, 0, 80, 24, attrs[TTY]);
if(!fp)
message_box("Unable to open CONFIG file: %s", buffer);
update_status();
w_puts(" Press CTRL-HOME or CTRL-END for menu", status);
open_comm();
IOB_size = 512;
if(!argc)
script(&argv[line-1]);
while(interactive) {
ansi_term();
if(!wmenu(5, 3, attrs[SETUP1], main_menu, &main_p)) switch(main_p) {
case 0 : /* Fast access script */
if(optr = file_menu(scripts, &script_p, 0)) {
parse_args(buffer);
script(buffer); }
break;
case 1 : /* Download */
if(optr = file_menu(protocols, &proto_p, 0))
file_transfer(0, 0);
break;
case 2 : /* Upload */
if(optr = file_menu(protocols, &proto_p, 0))
file_transfer(-1, 0);
break;
case 3 : /* Close capture */
if(log_fp)
fclose(log_fp);
log_fp = 0;
update_status();
break;
case 4 : /* Script by name */
if(!get_string("Script", optr = scriptfile, FSIZE)) {
parse_args(buffer);
script(buffer); }
break;
case 5 : /* Hangup */
hangup();
break;
case 6 : /* Clear screen */
wclwin();
break;
case 7 : /* Configure */
configure();
break;
case 8 : /* Shell to DOS */
doshell(0);
break;
case 9 : /* Exit */
interactive = 0; } }
if(log_fp)
fclose(log_fp);
if(hangmdm) {
signals &= ~(SET_DTR|SET_RTS);
open_comm(); }
Cclose();
wclose();
wclose();
}
/*
* Display a message in a box
*/
register message_box(args)
unsigned args;
{
unsigned *ptr, l;
char buffer[80];
ptr = nargs() * 2 + &args;
_format_(buffer, ptr);
l = strlen(buffer)+16;
wopen((80-l)/2, 10, l+2, 3, attrs[ERROR]);
wcursor_off();
wprintf(" %s (Press ENTER) ", buffer);
if(alarm) wputc(7);
while(wgetc() != '\n');
wclose();
}
/*
* Write a message into the status line
*/
register write_status(args)
unsigned args;
{
unsigned *ptr;
char buffer[80];
ptr = nargs() * 2 + &args;
_format_(buffer, ptr);
w_printf(status,"\r%s", buffer);
w_cleow(status);
}
/*
* Update status line
*/
update_status()
{
int i;
w_printf(status,"\rCOM%u: %5s-%u%c%u %c \xB3 %3s \xB3",
com_port+1, baudtext[baud], dbits+5, *paritytext[parity], sbits+1,
*flowtext[flow], log_fp ? "Cap" : "");
for(i=0; i < status_name_ptr; ++i)
w_printf(status," %s", status_names[i]);
w_cleow(status);
}
/*
* Open comm port with correct settings
*/
open_comm()
{
int mode;
/* Calculate the communications parameter value */
mode = ((parity << 4) & 0x30) | /* parity type */
(dbits & 0x03) | /* # data bits */
((sbits << 2) & 0x04) | /* # stop bits */
((parity < 4) << 3); /* parity enable */
/* Open the communications port */
if(Copen(com_port+1, baudvalue[baud], mode, signals)) {
message_box("Cannot open COM port %u!", com_port+1);
return 0; }
/* Remove transparency if XON/XOFF flow control */
disable();
Cflags = (flow) ? Cflags & ~TRANSPARENT : Cflags | TRANSPARENT;
enable();
return -1;
}
/*
* Hangup the modem
*/
hangup()
{
write_status("Hanging up the modem...");
signals &= ~(SET_DTR|SET_RTS);
open_comm();
wait_clear(hangup_delay);
signals |= (SET_DTR|SET_RTS);
open_comm();
update_status();
}
/*
* Write a string to the comm port
*/
Cputs(ptr)
char *ptr;
{
int c;
unsigned timeout;
while(*ptr) {
timeout = key_string_delay;
do {
if((c = Ctestc()) != -1)
receive_data(c);
if((c = Ctestc()) != -1)
receive_data(c); }
while(timeout--);
Cwrite(*ptr++); }
testabort();
}
/*
* Write char to comm port with echo if enabled
*/
Cwrite(c)
int c;
{
Cputc(c);
if(echosnd)
wputc(c);
}
/*
* Get a string from the console
*/
get_string(prompt, name, length)
char *prompt, *name;
int length;
{
int i, j;
i = (j = strlen(prompt))+length+7;
wopen((80-i)/2, 10, i, 3, attrs[STRING]);
for(;;) {
wgotoxy(1, 0);
wprintf("%s ? ", prompt);
switch(wgets(j+4, 0, name, length)) {
case 0x1B : /* Exit */
wclose();
return -1;
case '\n' : /* Select */
wclose();
return 0; } }
}
/*
* Open a file with options
*/
open_file(filename, options)
char *filename, *options;
{
int n, p, c, i;
char *names[100], namebuf[1000], *nptr, *ptr, *ptr1;
for(ptr = filename; i = *ptr; ++ptr)
if((i == '*') || (i == '?'))
break;
if(i) {
if(find_first(filename, n = 0, nptr = namebuf, &i, &i, &i, &i, &i)) {
message_box("No files found matching: '%s'", filename);
return 0; }
wopen(13, 5, 53, 12, attrs[STRING]);
wcursor_off();
do {
for(i=0; i < n; ++i)
if(strcmp(names[i], nptr) == 1)
break;
for(c = ++n; c > i; --c)
names[c] = names[c-1];
names[i] = nptr;
while(*nptr++); }
while((n < (sizeof(names)/2)) && !find_next(nptr, &i, &i, &i, &i, &i));
for(i=n; i < (sizeof(names)/2); ++i)
names[i] = "";
c = p = 0;
for(;;) {
for(i=0; i < 40; ++i) {
wgotoxy((i%4)*13, i/4);
*W_OPEN = (i == c) ? ((*W_OPEN >> 4)|(*W_OPEN << 4)) : attrs[STRING];
wputf(names[i+p], 12); }
switch(wgetc()) {
case 0x1B :
wclose();
return 0;
case '\n' :
ptr = ptr1 = filename;
while(i = *ptr++) {
if((i == '\\') || (i == ':'))
ptr1 = ptr; }
strcpy(ptr1, names[p+c]);
wclose();
goto open_file;
case _KRA : i = c + 1; goto position;
case _KLA : i = c - 1; goto position;
case _KUA : i = c - 4; goto position;
case _KDA : i = c + 4;
position:
if(i < 0) {
c = 0;
if((p - 4) >= 0) {
c = i + 4;
p -= 4; }
break; }
if(i >= 40) {
if((p + 40) < n) {
i -= 4;
p += 4; } }
c = ((p + i) < n) ? i : (n - p) - 1; } } }
open_file:
if(!options) /* Solve wildcards only ... don't open */
return -1;
if(!(fp = fopen(filename, options)))
message_box("Unable to access: '%s'", filename);
return fp;
}
/*
* Configuration menu
*/
configure()
{
int c, i, f, b;
char *ptr;
wopen(5, 3, 30, (sizeof(config_menu)/2)+1, WSAVE);
wcursor_off();
while(!wmenu(5, 3, attrs[SETUP2], config_menu, &config_p)) switch(config_p) {
case 0 : /* General switches */
ptr = &alarm;
wopen(28, 3, 40, (sizeof(switches)/2)+2, attrs[SETUP1]);
for(;;) {
for(i=0; i < (sizeof(switches)/2); ++i) {
wgotoxy(0, i);
wprintf("%u: %-31s= %c", i+1, switches[i], ptr[i] ? 'Y' : 'N'); }
if((i = wgetc()) == 0x1B) {
wclose();
break; }
if((i -= '1') < (sizeof(switches)/2))
ptr[i] = ptr[i] ? 0 : -1; }
break;
case 1 : /* General parameters */
wform(28, 3, attrs[SETUP1], setup_form, homedir, &tab_size, &hangup_delay,
&key_string_delay, &upl_char_delay, &upl_line_delay, &upl_sync_char);
break;
case 2 : /* Serial port setup */
wopen(28, 3, 30, (sizeof(serial_menu)/2)+1, WSAVE);
while(!wmenu(28, 3, attrs[SETUP2], serial_menu, &serial_p)) {
switch(serial_p) {
case 0 : wmenu(42, 3, attrs[SETUP1], onefour, &com_port); break;
case 1 : wmenu(42, 3, attrs[SETUP1], baudtext, &baud); break;
case 2 : wmenu(42, 3, attrs[SETUP1], paritytext, &parity); break;
case 3 : wmenu(42, 3, attrs[SETUP1], fiveight, &dbits); break;
case 4 : wmenu(42, 3, attrs[SETUP1], onetwo, &sbits); break;
case 5 : wmenu(42, 3, attrs[SETUP1], flowtext, &flow); }
update_status(); }
open_comm();
wclose();
break;
case 3 : /* Protocol setup */
wform(5, 13, attrs[SETUP1], string_form, protocols[0], protocols[1],
protocols[2], protocols[3], protocols[4], protocols[5],
protocols[6], protocols[7]);
break;
case 4 : /* Script setup */
wform(5, 13, attrs[SETUP1], string_form, scripts[0], scripts[1],
scripts[2], scripts[3], scripts[4], scripts[5], scripts[6],
scripts[7]);
break;
case 5 : /* Video attributes */
i = 0;
do {
f = attrs[i] & 0x0F;
b = (attrs[i] >> 4) & 0x0F;
wopen(28, 3, 40, 9, WSAVE|WCOPEN|WBOX2|(b<<4)|f);
*W_OPEN = (f << 4) + b;
wprintf("%-38s\n\n", menus[i]);
*W_OPEN = (b << 4) + f;
wputs("Left/Right = Foreground\nUp/Down = Background\n");
wputs("PgUp/PgDn = Select window\n\nPress ESCAPE to exit.");
c = wgetc();
wclose();
switch(c) {
case _KRA : f = (f+1) & 0x0F; goto newattr;
case _KLA : f = (f-1) & 0x0F; goto newattr;
case _KDA : b = (b+1) & 0x0F; goto newattr;
case _KUA : b = (b-1) & 0x0F;
newattr:
attrs[i] = (attrs[i] & 0xff00) | (b << 4) | f;
break;
case _KPD : if(++i >= (sizeof(menus)/2)) i = 0; break;
case _KPU : if(--i < 0) i = (sizeof(menus)/2)-1; } }
while(c != 0x1B);
break;
case 6 : /* Load configuration */
if(get_string(cnfprompt, optr = cnffile, FSIZE))
break;
parse_filename(buffer, cnfext);
if(open_file(buffer, "rb")) {
fread(homedir, ansi_keys-homedir, fp);
fclose(fp);
open_comm(); }
break;
case 7 : /* Save configuration */
if(get_string(cnfprompt, optr = cnffile, FSIZE))
break;
parse_filename(buffer, cnfext);
if(open_file(buffer, "wb")) {
fwrite(homedir, ansi_keys-homedir, fp);
fclose(fp); }
}
wclose();
update_config();
}
/*
* Update the displays to indiate a new configuration
*/
update_config()
{
if(*tty != (*attrs & 0xff)) {
*tty = *attrs;
w_clwin(tty); }
*status = attrs[STATUS];
update_status();
}
/*
* Terminal mode using ANSI (VT100) emulation
*/
ansi_term()
{
char c, xy_flag;
unsigned x, y, state, value, parm, parms[5];
xy_flag = -1; /* Force initial cursor update */
state = 0; /* Not receiving a control sequence */
for(;;) {
/* Process any input from the comm port */
if((c = Ctestc()) != -1) {
last_rx = c;
ansi_out:
if(log_fp && ((c >= ' ') || (c == '\t') || (c == '\n')))
putc(c, log_fp);
xy_flag = -1;
if(c == 0x1B) { /* Begin escape sequence */
state = 1;
parms[0] = parms[1] = value = parm = 0; }
else switch(state) {
case 1 : /* Escape already received */
if(c == '[') {
state = 2;
break; }
state = 0;
case 0 : /* No special processing */
if(c == '\t') {
do
wputc(' ');
while(tty[6] % tab_size);
break; }
wputc(c);
break;
case 2 : /* Waiting for numeric parms */
if(isdigit(c)) {
value = (value * 10) + (c - '0');
break; }
parms[parm++] = value; /* More to come */
if(c == ';') {
value = 0;
break; }
state = 0;
switch(c) {
case 'H' : /* Cursor position (1) */
case 'f' : /* Cursor position (2) */
if(y = parms[0])
--y;
if(x = parms[1])
--x;
wgotoxy(x, y);
break;
case 'J' : /* Erase in display */
x = tty[6]; y = tty[7];
value ? wclwin() : wcleow();
tty[6] = x; tty[7] = y;
break;
case 'K' : /* Erase in line */
if(value)
tty[6] = 0;
wcleol();
break;
case 'm' : /* Select attributes */
if((x = parms[0]) > 7)
x = 0;
*tty = attrs[x]; } } }
else if(xy_flag) { /* Cursor has moved */
wupdatexy();
xy_flag = 0; }
/* Process any input from the keyboard */
if(c = get_key()) {
if(c == EOF)
return;
Cputc(c);
if(echotty)
goto ansi_out; } }
}
/*
* Read a key from the keyboard
*/
get_key()
{
int c;
if(key_delay) {
--key_delay;
return 0; }
if(upl_fp) {
if(c = wtstc()) switch(c) {
case 0x1B :
abort_flag = -1;
goto abort;
case ' ' :
last_rx = upl_sync_char; }
key_delay = upl_char_delay;
switch(sent_cr) {
case ' ' : /* Expanded NULL line */
goto sendcr;
case '\r' : /* Just sent return */
if(sendlf)
return sent_cr = 0x0A;
case 0x0A : /* Just sent line-feed */
if(upl_sync_char) {
if(last_rx != upl_sync_char)
return key_delay = 0; }
sent_cr = -1; }
if((c = getc(upl_fp)) != EOF) {
if(c == '\n') {
if(sendnull && sent_cr)
return sent_cr = ' ';
sendcr: key_delay = upl_line_delay;
return sent_cr = '\r'; }
sent_cr = 0;
return c; }
abort: fclose(upl_fp);
upl_fp = sent_cr = 0;
update_status(); }
if(key_ptr) {
if(c = *key_ptr++) {
key_delay = key_string_delay;
return c; }
key_ptr = 0; }
if((c = wtstc()) & 0x80) {
return (key_ptr = ansi_keys[c & 0x7f]) ? 0 : -1; }
return (c == '\n') ? '\r' : c;
}
/*
* Execute a sub-shell
*/
doshell(command)
char *command;
{
char comspec[65], tail[80];
if(!getenv("COMSPEC", comspec)) {
message_box("Cannot locate COMSPEC");
return; }
*tail = 0;
if(command)
concat(tail, "/C ", command);
wopen(0, 0, 80, 25, WSAVE|WCOPEN|0x07);
wupdatexy();
exec(comspec, tail);
wclose();
}
/*
* Perform a file transfer
*/
file_transfer(upload, name)
char upload, *name;
{
int i, c;
char buffer[6], cmd[100], zap, wait, ascii;
char *ptr1, *ptr2, *ptr3;
wait = zap = ascii = i = 0;
ptr1 = parse_filename(cmd, ".COM");
ptr2 = ++ptr1;
while(c = *optr++) {
if(c == '\\') switch(c = *optr++) {
case 'Z' : zap = -1; continue; /* Zap screen */
case 'W' : wait = -1; continue; /* Wait after run */
case 'A' : ascii = -1; continue; /* ASCII transfer */
case 'P' : ptr3 =paritytext[parity];goto copy; /* Parity */
case 'B' : ptr3 = baudtext[baud]; goto copy; /* Baudrate */
case 'H' : ptr3 = homedir; goto copy; /* Home dir */
case 'N' : c = dbits + 5; goto wrnum; /* Data bits */
case 'S' : c = sbits + 1; goto wrnum; /* Stop bits */
case 'C' : c = com_port + 1; /* Comm port */
wrnum:
sprintf(ptr3 = buffer,"%u", c);
copy:
while(c = *ptr3++)
*ptr1++ = c;
continue;
case 'G' : /* Upload filename */
case 'Y' : /* Upload with wildcards */
if(!upload)
continue;
case 'F' : /* Filename */
case 'X' : /* Allow wildcards */
if(!(ptr3 = name)) {
if(get_string(upload ? uplprompt : dnlprompt, ptr3 = name = filename, FSIZE))
return; }
if(((c == 'F') || (c == 'G')) && !open_file(name, 0))
return;
goto copy;
case 'U' : /* Upload string */
while((c = *optr++) && (c != '\\'))
if(upload)
*ptr1++ = c;
continue;
case 'D' : /* Download string */
while((c = *optr++) && (c != '\\'))
if(!upload)
*ptr1++ = c;
continue; }
*ptr1++ = c; }
*ptr1 = 0;
/* Process ASCII transfers */
if(ascii) {
while(isspace(*ptr2)) ++ptr2;
if(upload) {
if(upl_fp = open_file(ptr2, "r"))
write_status("ASCII upload of '%s'...", ptr2); }
else {
if(log_fp)
fclose(log_fp);
log_fp = open_file(ptr2, "w");
update_status(); }
return; }
/* Execute the external protocol */
write_status("%s of '%s'...", upload ? "Upload" : "Download", name);
Cclose();
if(zap) wopen(0, 0, 80, 25, WSAVE|WCOPEN|0x07);
wupdatexy();
i = exec(cmd, ptr2);
if(wait) {
write_status("Press enter to continue...");
while(wtstc() != '\n'); }
if(zap) wclose();
open_comm();
update_status();
if(i)
message_box("Error %u returned from '%s'!", i, cmd);
}
/*
* Build an entry from a file list
*/
file_menu(files, pointer, name)
char files[NFILES][FWIDTH], *name;
int *pointer;
{
int i, j, c;
char *names[NFILES+1], *pptr[NFILES], buffer[100], *ptr, *ptr1, *ptr2;
/* Build menu from filenames */
ptr1 = buffer;
for(i=j=0; i < NFILES; ++i) {
if(*(ptr = files[i])) {
pptr[j] = ptr;
names[j++] = ptr2 = ptr1;
while(c = *ptr++) {
if(isspace(c) || (c == ';'))
break;
else if((c == '\\') || (c == ':'))
ptr1 = ptr2;
else
*ptr1++ = c; }
*ptr1++ = 0; }
if(name && strbeg(ptr2, name)) {
ptr = ptr1 = pptr[j-1];
goto strip_name; } }
names[j] = 0;
if(!j) {
message_box("No selections configured!");
return 0; }
if(wmenu(5, 3, attrs[SETUP1], names, pointer))
return 0;
/* Strip off any leading name */
ptr = ptr1 = pptr[*pointer];
strip_name:
while((c = *ptr++) && !isspace(c)) {
if(c == ';')
return ptr; }
return ptr1;
}
/*
* Execute a script command file
*/
script(argv)
char *argv[];
{
unsigned c, i;
char buffer[80], buffer1[80], *ptr, *ptr1;
char variables[NUM_VARS][50];
FILE *sfp;
chain_script:
abort_flag = invisible = 0;
status_names[status_name_ptr++] = optr = argv[0];
parse_filename(buffer, ".SCR");
if(!(sfp = open_file(buffer, "r")))
goto exit1;
update_status();
/* zero out the variables */
for(line=i=0; i < NUM_VARS; ++i)
*variables[i] = 0;
flush_capture(0);
while(fgets(optr = buffer, sizeof(buffer), sfp)) {
++line;
/* Skip any label */
if(skip_blanks() == ':')
while(*optr && !isspace(*optr))
++optr;
next_cmd_string:
wupdatexy();
/* Substitute any variables etc. */
ptr = buffer1;
while((c = *optr++) && (c != ';')) {
if(c == '\\') switch(c = *optr++) {
case 'b' : c = 0x08; break;
case 'd' : c = 0x7F; break;
case 'e' : c = 0x1B; break;
case 'r' : c = 0x0D; break;
case '#' :
c = 0;
while(isdigit(*optr))
c = (c*10) + (*optr++ - '0');
break;
case 's' :
sprintf(ptr, "%u", Csignals());
while(*++ptr);
continue;
default:
if((i = c - '0') < 10)
ptr1 = argv[i];
else if((i = c - 'A') < NUM_VARS)
ptr1 = variables[i];
else if(c == 'n')
ptr1 = "\r\n";
else if(c == 'h')
ptr1 = homedir;
else
break;
if(ptr1) while(*ptr1)
*ptr++ = *ptr1++;
continue; }
else if(c == '^')
c = *optr++ & 0x1f;
*ptr++ = c; }
while(isspace(*--ptr) && (ptr >= buffer1));
*++ptr = 0;
optr = buffer1;
continue_command:
testabort();
if(abort_flag)
goto exit;
if(*optr) switch(i = lookup(commands)) {
case 0 : /* Print */
wprintf("%s\n\r",optr);
break;
case 1 : /* Echo */
wputs(optr);
break;
case 2 : /* Assign */
case 3 : /* Equate */
case 4 : /* Input */
case 5 : /* Read */
case 6 : /* Menu */
if((c = *optr++ - 'A') >= NUM_VARS) {
script_error("Invalid variable name");
goto exit; }
skip_blanks();
ptr = variables[c];
switch(i) {
case 2 : strcpy(ptr, optr); break;
case 3 : sprintf(ptr, "%d", eval()); break;
case 4 :
if(get_string(optr, ptr, sizeof(variables[0])-1))
goto exit;
break;
case 5 :
Cputs(optr);
i = 0;
do {
do
if(testabort()) goto exit;
while((c = Ctestc()) == -1);
if((c == '\b') || (c == 0x7f)) {
if(i) {
--i;
Cputs("\b \b"); } }
else if(c >= ' ')
Cwrite(ptr[i++] = c); }
while(c != '\r');
ptr[i] = 0;
Cputs("\n\r");
break;
case 6 :
parse_args(buffer);
c = 0;
sprintf(ptr,"%d", wmenu(5, 3, attrs[SETUP1], buffer, &c) ?
-1 : c); }
break;
case 7 : /* If# */
if(eval()) {
expect(':');
goto continue_command; }
break;
case 8 : /* Ifeq */
case 9 : /* ifne */
parse_string(buffer);
parse_string(buffer+40);
expect(':');
if(i == 8) {
if(!strcmp(buffer, buffer+40))
goto continue_command; }
else {
if(strcmp(buffer, buffer+40))
goto continue_command; }
break;
case 10 : /* Ifnot */
parse_string(buffer);
expect(':');
if(!search_buffer(buffer))
goto continue_command;
break;
case 11 : /* If */
parse_string(buffer);
expect(':');
if(search_buffer(buffer))
goto continue_command;
break;
case 12 : /* Goto */
if(*optr == '+')
++optr;
else {
rewind(sfp);
line = 0; }
ptr = optr;
search_next:
while(fgets(optr = buffer, sizeof(buffer), sfp)) {
++line;
if(skip_blanks() == ':') {
++optr;
ptr1 = ptr;
while(*optr && !isspace(*optr)) {
if(*optr++ != *ptr1++)
goto search_next; }
if(isspace(*ptr1) || !*ptr1)
goto next_cmd_string; } }
script_error("Label not found");
case 13 : /* Skip */
for(i = eval(); i; --i)
if(!fgets(buffer, sizeof(buffer), sfp))
goto exit;
case 14 : /* Stop */
goto exit;
case 15 : /* Call */
i = line;
c = invisible;
parse_args(buffer);
script(buffer);
invisible = c;
line = i;
break;
case 16 : /* Chain */
fclose(sfp);
parse_args(argv);
--status_name_ptr;
goto chain_script;
case 17 : /* Send */
Cputs(optr);
break;
case 18 : /* Scan */
flush_capture(0);
if(parse_string(buffer))
if(!wait_string(buffer, eval()+1))
if(*optr) {
expect(':');
goto continue_command; }
break;
case 19 : /* Flush */
while((c = Ctestc()) != -1)
receive_data(c);
flush_capture(*buffer ? buffer : 0);
break;
case 20 : /* Wait */
wait_clear(eval());
break;
case 21 : /* Upload */
case 22 : /* Download */
ptr = optr;
while((c = *optr) && !isspace(c)) ++optr;
if(c)
*optr++ = 0;
ptr1 = skip_blanks() ? optr : 0;
if(optr = file_menu(protocols, &proto_p, ptr)) {
if(i == 21) {
file_transfer(-1, ptr1);
while(upl_fp) {
while((c = Ctestc()) != -1)
receive_data(c);
if(c = get_key())
Cwrite(c); } }
else
file_transfer(0, ptr1); }
break;
case 23 : /* Close */
if(log_fp) {
fclose(log_fp);
log_fp = 0; }
update_status();
break;
case 24 : /* Dos */
doshell(optr);
break;
case 25 : invisible = 0; break; /* Visible */
case 26 : invisible = -1; break; /* Invisible */
case 27 : /* Abort */
script_error(optr);
break;
case 28 : /* Error */
abort_flag = -1;
case 29 : /* Message */
message_box(optr);
break;
case 30 : /* Hangup */
hangup();
break;
case 31 : /* Terminal */
ansi_term();
break;
case 32 : /* Clear */
wclwin();
break;
case 33 : /* Config */
parse_filename(buffer, cnfext);
if(open_file(buffer, "rb")) {
fread(homedir, ansi_keys-homedir, fp);
fclose(fp);
open_comm();
update_config(); }
break;
case 34 : /* Exittodos */
interactive = 0;
abort_flag = -1;
goto exit;
default:
script_error("Unknown command");
goto exit;
case 35 : } } /* Remark */
exit:
fclose(sfp);
exit1:
if(upl_fp) {
fclose(upl_fp);
upl_fp = 0; }
--status_name_ptr;
update_status();
}
/*
* Evaluate an expression and return its numeric value
*/
eval()
{
int o, v, v1;
char vflag, mflag;
v1 = o = 0;
do {
if(!*optr) {
script_error("Incomplete expression");
return 0; }
mflag = vflag = v = 0;
if(*optr == '-') {
++optr;
mflag = -1; }
if(*optr == '(') {
++optr;
v = eval();
if(expect(')'))
return; }
else {
while(isdigit(*optr)) {
v = (v * 10) + (*optr++ - '0');
vflag = -1; }
if(!vflag) {
script_error("Invalid number");
return 0; } }
if(mflag) v = -v;
switch(o) {
case 0 : v1 += v; break;
case 1 : v1 -= v; break;
case 2 : v1 *= v; break;
case 3 : v1 /= v; break;
case 4 : v1 %= v; break;
case 5 : v1 &= v; break;
case 6 : v1 |= v; break;
case 7 : v1 ^= v; break;
case 8 : v1 <<= v; break;
case 9 : v1 >>= v; break;
case 10: v1 = v1 == v; break;
case 11: v1 = v1 != v; break;
case 12: v1 = v1 >= v; break;
case 13: v1 = v1 <= v; break;
case 14: v1 = v1 > v; break;
case 15: v1 = v1 < v; }
o = lookup(operators); }
while(operators[o]);
if((o = *optr) && (o != ':') && (o != ')')) {
script_error("Invalid operation");
return 0; }
return v1;
}
/*
* Determine if a character is a space
*/
isspace(c)
int c;
{
return (c == ' ') || (c == '\t');
}
/*
* Lookup in table entry in command strinf
*/
lookup(table)
char **table;
{
int i;
char *ptr;
skip_blanks();
for(i=0; ptr = table[i]; ++i)
if(strbeg(optr, ptr)) {
optr += strlen(ptr);
break; }
skip_blanks();
return i;
}
/*
* Skip ahead past leading blanks
*/
skip_blanks()
{
while(isspace(*optr))
++optr;
return *optr;
}
/*
* Expect a character in the input buffer
*/
expect(c)
int c;
{
if(skip_blanks() == c) {
++optr;
return 0; }
script_error("Syntax error");
return -1;
}
/*
* Test for the abort key and indicate if pressed
*/
testabort()
{
if(wtstc() == 0x1B) {
script_error("User abort");
return -1; }
return 0;
}
/*
* Indicate an error occuring in a script file
*/
script_error(string)
char *string;
{
wprintf("** line %u: %s\n\r", line, string);
abort_flag = -1;
}
/*
* Parse a delimited string from (optr)
*/
parse_string(output)
char *output;
{
int d, c;
if(d = skip_blanks()) {
while(c = *++optr) {
if(c == d) {
++optr;
*output = 0;
skip_blanks();
return -1; }
*output++ = c; } }
script_error("Improper string");
return 0;
}
/*
* Parse string(OPTR) into 10 ARGC, ARGV parameters
*/
parse_args(outbuf)
char *outbuf[];
{
int i;
char *ptr;
i = 0;
ptr = &outbuf[10];
while(skip_blanks()) {
outbuf[i++] = ptr;
while(*optr && !isspace(*optr))
*ptr++ = *optr++;
*ptr++ = 0; }
while(i < 10)
outbuf[i++] = 0;
}
/*
* Parse a filename from (optr)
*/
parse_filename(dest, suffix)
char *dest, *suffix;
{
int c, d;
char *ptr;
/* Test for direcrtory supplied */
d = '\\';
ptr = optr;
while((c = *ptr++) && !isspace(c)) {
if((c == '\\') || (c == ':'))
d = 0; }
/* If no directory, prepend home directory */
if(d) {
ptr = homedir;
while(c = *ptr++)
*dest++ = d = c;
if(d != '\\')
*dest++ = '\\'; }
/* Copy in filename */
d = -1;
while((c = *optr) && !isspace(c)) {
++optr;
if((*dest++ = c) == '.')
d = 0; }
/* Append suffix if requested */
if(d && suffix) {
while(c = *suffix++)
*dest++ = c; }
*dest = 0;
return dest;
}
/*
* Flush the capture buffer and optionally insert a string
*/
flush_capture(ptr)
char *ptr;
{
register unsigned i;
for(cptr = i = 0; i < CAPTURE_SIZE; ++i)
capture[i] = 0;
if(ptr) {
while(*ptr)
capture[cptr++] = *ptr++; }
}
/*
* Handle data received from the remote
*/
receive_data(c)
char c;
{
capture[cptr] = last_rx = c;
if(++cptr >= CAPTURE_SIZE)
cptr = 0;
/* echo char if selected */
if(!invisible)
wputc(c);
/* Write download file if selected */
if(log_fp && ((c >= ' ') || (c == '\t') || (c == '\n')))
putc(c, log_fp);
}
/*
* Wait for string from remote
*/
wait_string(string, ticks)
char *string;
unsigned ticks;
{
int c;
unsigned j, s, os;
char *ptr, *ptr1, *ptr2, buffer[50], flag;
os = -1;
flag = 0;
ptr = buffer;
do {
if((c = Ctestc()) >= 0) {
receive_data(*ptr++ = c);
*ptr = 0; flag = -1; }
else if(testabort())
return 0;
if(flag) {
ptr1 = string;
ptr2 = buffer;
while(*ptr2 && (*ptr2 == *ptr1)) {
++ptr1; ++ptr2; }
if(*ptr2) { /* strings do not match at all */
for(ptr1 = buffer; ptr1 < ptr; ++ptr1)
*ptr1 = *(ptr1+1);
--ptr; }
else if(*ptr1) /* Partial match, wait for more chars */
flag = 0;
else /* Full match - we found it */
return -1 ; }
get_time(&j, &j, &s);
if(s != os) {
os = s;
--ticks; } }
while(ticks);
return 0;
}
/*
* Search the capture buffer for a string
*/
search_buffer(string)
char *string;
{
char *ptr;
unsigned sptr, rptr;
sptr = cptr;
do {
rptr = sptr;
ptr = string;
while(*ptr && (*ptr == capture[rptr])) {
++ptr;
if(++rptr >= CAPTURE_SIZE)
rptr = 0; }
if(!*ptr) /* we found it */
return 11;
if(++sptr >= CAPTURE_SIZE) /* advance scan pointer */
sptr = 0; }
while(sptr != cptr);
return 0;
}
/*
* Wait until no data is received
*/
wait_clear(ticks)
unsigned ticks;
{
int c, t;
unsigned j, s, os;
os = -1;
t = ++ticks;
do {
if((c = Ctestc()) != -1) {
receive_data(c);
t = ticks; }
else {
if(testabort())
return;
get_time(&j, &j, &s);
if(s != os) {
os = s;
--t; } } }
while(t);
}